<?php
include_once "settings.inc";
include_once "fill-info.inc";

function connectDB() {
    global $dbHost, $dbUser, $dbPassword, $dbName;
    $connection = mysql_connect($dbHost, $dbUser, $dbPassword);
    mysql_select_db($dbName, $connection);
    mysql_query("SET NAMES ‘utf8′ COLLATE ‘utf8_unicode_ci’;", $connection);
    mysql_query("SET CHARACTER SET utf8", $connection);
    mysql_query("SET NAMES utf8", $connection);
    return $connection;
}

function closeDB($connection) {
    mysql_close($connection);
}

function myQuery($conn, $query, $params) {
    global $debug;
    $str = $query;
    $res = "";
    $i = 0;
    while ($i < count($params) && ($pos = strpos($str, "?")) !== FALSE) {
        if ($params[$i] !== null)
            $val = "'" . mysql_real_escape_string($params[$i], $conn) . "'";
        else
            $val = "NULL";
        $res = $res . substr($str, 0, $pos) . $val;
        $str = substr($str, $pos + 1);
        $i++;
    }
    $res = $res . $str;
    $str = $res;
    if ($debug > 1) {
        echo "Executing query: $str\n";
    }
    $res = mysql_query($str, $conn);
    if ($debug > 1)
        echo "Result = $res\n";
    return $res;
}

function cleanupExpiredInternal($conn, $cur_time, $force = false) {
    global $cleanupPeriod, $sqlDatetime;
    static $last_cleanup = 0;
    $res = 1;
    if ($force || $cur_time - $last_cleanup >= $cleanupPeriod) {
        $res = myQuery($conn, "delete from sessions where expire <= ?;", array(date($sqlDatetime, $cur_time)));
        $last_cleanup = $cur_time;
    }
    return $res;
}

function verifyHash($hash) {
   return preg_match("/^[0-9a-f]{40}$/", $hash);
}

function verifyUid($uid) {
    return is_numeric($uid) && ($uid >= 1);
}

function verifyGid($gid) {
    return is_numeric($gid) && ($gid >= 1);
}

function addNewUser() {
    $uid = 0;
    $conn = connectDB();
    $res = myQuery($conn, "insert into users set cur_gid=NULL;", array());
    if ($res)
        $uid = mysql_insert_id($conn);
    closeDB($conn);
    return $uid;
}

function addNewGame($uid) {
    if (!verifyUid($uid))
        return 0;
    $gid = 0;
    $conn = connectDB();
    $res = myQuery($conn, "insert into games set uid=?;", array($uid));
    if ($res) {
        $gid = mysql_insert_id ($conn);
        myQuery($conn, "update users set cur_gid=? where uid=?;", array($gid, $uid));
    }
    closeDB($conn);
    return $gid;
}

function fillDefaultValues($counts) {
    $res = array();
    $names = array("s", "w", "o", "t");
    for ($i = 0; $i < 4; $i++) {
        $res['counts'][$i] = $counts[$i];
        for ($j = 0; $j < $counts[$i]; $j++) {
            $res['swots'][$i][$j]['caption'] = $names[$i] . ($j + 1);
            $res['swots'][$i][$j]['valuability'] = 2;
        }
    }
    $matrices = array(array(0, 2), array(0, 3), array(1, 2), array(1, 3));
    for ($i = 0; $i < 4; $i++)
        for ($j1 = 0; $j1 < $counts[$matrices[$i][0]]; $j1++)
            for ($j2 = 0; $j2 < $counts[$matrices[$i][1]]; $j2++)
                $res['matrices'][$i][$j1][$j2] = 2;
    return $res;
}

function appendDefaultValues(&$values) {
    $counts = array();
    for ($i = 0; $i < 4; $i++) {
        $counts[$i] = $values['counts'][$i];
        for ($j = 0; $j < $counts[$i]; $j++)
            if (!isset($values['swots'][$i][$j]['valuability']))
                $values['swots'][$i][$j]['valuability'] = 2;
    }
    $matrices = array(array(0, 2), array(0, 3), array(1, 2), array(1, 3));
    for ($i = 0; $i < 4; $i++)
        for ($j1 = 0; $j1 < $counts[$matrices[$i][0]]; $j1++)
            for ($j2 = 0; $j2 < $counts[$matrices[$i][1]]; $j2++)
                if (!isset($values['matrices'][$i][$j1]) || !isset($values['matrices'][$i][$j1][$j2]))
                    $values['matrices'][$i][$j1][$j2] = 2;
}

function hasNotDefaultSwots($values, $type) {
    $names = array("s", "w", "o", "t");
    for ($i = 0; $i < $values['counts'][$type]; $i++)
        if ($values['swots'][$type][$i]['caption'] != $names[$type] . ($i + 1) || $values['swots'][$type][$i]['valuability'] != 2)
            return 1;
    return 0;
}

function hasNotDefaultRelations($values, $type, $index) {
    for ($t = 2; $t < 4; $t++)
        for ($i = 0; $i < $values['counts'][$t]; $i++)
            if ($values['matrices'][$type * 2 + $t - 2][$index][$i] != 2)
                return 1;
}

function setValues($gid, $values) {
    if (!verifyGid($gid))
        return 0;
    $conn = connectDB();
    myQuery($conn, "delete from swots where gid=?;", array($gid));
    myQuery($conn, "delete from matrices where gid=?;", array($gid));

    // Minimum available information
    $counts = array();
    for ($i = 0; $i < 2; $i++)
        $counts[$i] = min($values['counts'][$i], count($values['swots'][$i]), count($values['matrices'][2 * $i]), count($values['matrices'][2 * $i + 1]));
    for ($i = 2; $i < 4; $i++) {
        $counts[$i] = min($values['counts'][$i], count($values['swots'][$i]));
        for ($j = 0; $j < $counts[0]; $j++)
            $counts[$i] = min($counts[$i], count($values['matrices'][$i - 2][$j]));
        for ($j = 0; $j < $counts[1]; $j++)
            $counts[$i] = min($counts[$i], count($values['matrices'][$i][$j]));
    }

    for ($i = 0; $i < 4; $i++)
        for ($j = 0; $j < $counts[$i]; $j++)
            myQuery ($conn, "insert into swots set gid=?, type=?, caption=?, valuability=?;", array($gid, $i, $values['swots'][$i][$j]['caption'],
                    $values['swots'][$i][$j]['valuability']));
    $matrices = array(array(0, 2), array(0, 3), array(1, 2), array(1, 3));
    for ($i = 0; $i < 4; $i++)
        for ($j1 = 0; $j1 < $counts[$matrices[$i][0]]; $j1++)
            for ($j2 = 0; $j2 < $counts[$matrices[$i][1]]; $j2++)
                myQuery($conn, "insert into matrices set gid=?, type=?, sw_index=?, ot_index=?, value=?;", array($gid, $i, $j1, $j2,
                        $values['matrices'][$i][$j1][$j2]));
    closeDB($conn);
}

function createSession($uid, $expireTime) {
    global $sqlDatetime;
    if (!verifyUid($uid))
        return 0;
    $sid = sha1(date(DATE_RFC1123) . rand());
    $conn = connectDB();
    myQuery($conn, "insert into sessions set sid=?, uid=?, expire=?;", array($sid, $uid, date($sqlDatetime, $expireTime)));
    closeDB($conn);
    return $sid;
}

function prolongateSession($sid, $expireTime) {
    global $sqlDatetime;
    if (!verifyHash($sid))
        return 0;
    $conn = connectDB();
    myQuery($conn, "update sessions set expire=? where sid=?;", array(date($sqlDatetime, $expireTime), $sid));
    cleanupExpiredInternal($conn, time());
    closeDB($conn);
}

function deleteSession($sid) {
    if (!verifyHash($sid))
        return 0;
    $conn = connectDB();
    myQuery($conn, "delete from sessions where sid=?;", array($sid));
    cleanupExpiredInternal($conn, time());
    closeDB($conn);
}

function getUid($sid) {
    if (!verifyHash($sid))
        return 0;
    $conn = connectDB();
    cleanupExpiredInternal($conn, time());
    $res = myQuery($conn, "select uid from sessions where sid=?;", array($sid));
    $uid = 0;
    if ($res && mysql_num_rows($res) == 1)
        $uid = mysql_result($res, 0, 0);
    closeDB($conn);
    return $uid;
}

function getAuthorized($uid) {
    if (!verifyUid($uid))
        return 0;
    $ret = 0;
    $conn = connectDB();
    $res = myQuery($conn, "select identity from users where uid=?;", array($uid));
    if ($res && mysql_num_rows($res) == 1) {
        $identity = mysql_result($res, 0, 0);
        if (!is_null($identity))
            $ret = 1;
    }
    closeDB($conn);
    return $ret;
}

function setIdentity($uid, $identity) {
    if (!verifyUid($uid))
        return 0;
    $ident_hash = sha1($identity);
    if (!verifyHash($ident_hash))
        return 0;
    $conn = connectDB();
    $res = myQuery($conn, "update users set identity=?, ident_hash=? where uid=?;", array($identity, $ident_hash, $uid));
    closeDB($conn);
}

function searchUid($identity) {
    $uid = 0;
    $ident_hash = sha1($identity);
    if (!verifyHash($ident_hash))
        return 0;
    $conn = connectDB();
    $res = myQuery($conn, "select uid,identity from users where ident_hash=?;", array($ident_hash));
    if ($res) {
        while ($row = mysql_fetch_assoc($res)) {
            if ($identity == $row['identity']) {
                $uid = $row['uid'];
                break;
            }
        }
    }
    closeDB($conn);
    return $uid;
}

function getCurrentGid($uid, &$game) {
    if (!verifyUid($uid))
        return 0;
    $conn = connectDB();
    $res = myQuery($conn, "select cur_gid from users where uid=?;", array($uid));
    $gid = 0;
    if ($res && mysql_num_rows($res) == 1) {
        $ok = 0;
        $gid = mysql_result($res, 0, 0);
        if (verifyGid($gid)) {
            $ok = 1;
            $res = myQuery($conn, "select * from games where gid=?;", array($gid));
        } else {
            $gid = 0;
            $res = myQuery($conn, "select * from games where uid=? order by gid desc limit 1;", array($uid));
            if ($res && mysql_num_rows($res) == 1) {
                $ok = 1;
                $gid = mysql_result($res, 0, 'gid');
                myQuery($conn, "update users set cur_gid=? where uid=?;", array($gid, $uid));
            }
        }
        $game['gid'] = $gid;
        if ($ok) {
            $game['scheme'] = mysql_result($res, 0, 'scheme_type');
            $game['caption'] = mysql_result($res, 0, 'caption');
            $game['comments'] = mysql_result($res, 0, 'comments');
            $game['public'] = mysql_result($res, 0, 'public');
        }
    }
    closeDB($conn);
    return $gid;
}

function isOwner($uid, $gid) {
    if (!verifyUid($uid) || !verifyGid($gid))
        return 0;
    $conn = connectDB();
    $result = myQuery($conn, "select * from games where gid=? and uid=?;", array($gid, $uid));
    if ($result && mysql_num_rows($result) >= 1)
        $res = 1;
    else
        $res = 0;
    closeDB($conn);
    return $res;
}

function setCurrentGid($uid, $gid) {
    if (!verifyUid($uid) || !verifyGid($gid))
        return 0;
    $conn = connectDB();
    $result = myQuery($conn, "update users set cur_gid=? where uid=?;", array($gid, $uid));
    closeDB($conn);
}

function loadValues($gid) {
    if (!verifyGid($gid))
        return 0;
    $res = array();
    $conn = connectDB();
    $result = myQuery($conn, "select * from swots where gid=? order by ordering asc;", array($gid));
    if ($result) {
        $counts = array(0, 0, 0, 0);
        while ($row = mysql_fetch_assoc($result)) {
            $type = $row['type'];
            $curCount = $counts[$type];
            $res['swots'][$type][$curCount]['caption'] = $row['caption'];
            $res['swots'][$type][$curCount]['valuability'] = $row['valuability'];
            $counts[$type]++;
        }
    }
    for ($i = 0; $i < 4; $i++)
        $res['counts'][$i] = $counts[$i];
    $result = myQuery($conn, "select * from matrices where gid=?;", array($gid));
    if ($result) {
        while ($row = mysql_fetch_assoc($result)) {
            $res['matrices'][$row['type']][$row['sw_index']][$row['ot_index']] = $row['value'];
        }
    }
    closeDB($conn);
    return $res;
}

function getAllGames($uid) {
    if (!verifyUid($uid))
        return 0;
    $res = array();
    $conn = connectDB();
    $result = myQuery($conn, "select * from games where uid=?;", array($uid));
    if ($result && mysql_num_rows($result) >= 1) {
        while ($row = mysql_fetch_assoc($result)) {
            $res[count($res)]['gid'] = $row['gid'];
            $res[count($res) - 1]['caption'] = $row['caption'];
        }
    }
    closeDB($conn);
    return $res;
}

function deleteGame($gid) {
    if (!verifyGid($gid))
        return 0;
    $conn = connectDB();
    myQuery($conn, "delete from games where gid=?;", array($gid));
    closeDB($conn);
}

function setGameOptions($gid, $game) {
    if (!verifyGid($gid))
        return 0;
    $conn = connectDB();
    $result = myQuery($conn, "update games set scheme_type=?, caption=?, comments=?, public=? where gid=?;", array($game['scheme'], $game['caption'],
            $game['comments'], $game['public'], $gid));
    closeDB($conn);
}

function loadIfPublic($gid, &$uid, &$game, &$values) {
    if (!verifyGid($gid))
        return 0;
    $res = 0;
    $conn = connectDB();
    $result = myQuery($conn, "select * from games where gid=? and public=1;", array($gid));
    closeDB($conn);
    if ($result && mysql_num_rows($result) == 1) {
        $uid = mysql_result($result, 0, 'uid');
        $game['gid'] = $gid;
        $game['scheme'] = mysql_result($result, 0, 'scheme_type');
        $game['caption'] = mysql_result($result, 0, 'caption');
        $game['comments'] = mysql_result($result, 0, 'comments');
        $game['public'] = mysql_result($result, 0, 'public');
        $values = loadValues($gid);
        $res = 1;
    }
    return $res;
}

function loadAllPublic() {
    $conn = connectDB();
    $res = array();
    $result = myQuery($conn, "select * from games where public=1;", array());
    while ($row = mysql_fetch_assoc($result)) {
        $res[count($res)]['gid'] = $row['gid'];
        $res[count($res) - 1]['caption'] = $row['caption'];
    }
    closeDB($conn);
    return $res;
}

function byScheme($val, $scheme) {
    $tbl = array(array(array(0.7, 1.0), array(0.0, 0.3), array(0.2, 0.8), array(0.7, 1.0), array(0.0, 0.3)),
            array(array(0.5, 1.0), array(0.0, 0.5), array(0.0, 1.0), array(0.5, 1.0), array(0.0, 0.5)),
            array(array(0.7, 1.0), array(0.0, 0.3), array(0.2, 0.8), array(0.4, 0.8), array(0.2, 0.6)));
    $mi = $tbl[$scheme][$val][0];
    $ma = $tbl[$scheme][$val][1];
    return rand($mi * 10, $ma * 10);	
}

function calcResults($values, $scheme) {
    $res = array();
    // Reserve places for general ratings, that are sums of partial
    $rt = array(array(array(), array(0), array(1)), array(array(), array(2), array(3)));
    $matrices = array(array(0, 2), array(0, 3), array(1, 2), array(1, 3));
    // Several resulting matrices
    for ($i = 0; $i < count($rt); $i++)
        for ($j = 0; $j < count($rt[$i]); $j++) {
            // Intermediate array for ranking
            $acc = array();
            // Calculate elements for ranking
            $lines = $values['counts'][$matrices[$rt[$i][$j][0]][0]];
            for ($n = 0; $n < $lines; $n++) {
                $sum = 0;
                // reduce result fluctuations
                for ($prog = 0; $prog < 10; $prog++)
                    for ($k = 0; $k < count($rt[$i][$j]); $k++) {
                        for ($l = 0; $l < $values['counts'][$matrices[$rt[$i][$j][$k]][1]]; $l++)
                            $sum += byScheme($values['matrices'][$rt[$i][$j][$k]][$n][$l], $scheme) *
                                    byScheme($values['swots'][$matrices[$rt[$i][$j][$k]][1]][$l]['valuability'], $scheme);
                    }
                $acc[$n] = round($sum / 10);
            }
            // Store
            for ($n = 0; $n < $lines; $n++) {
                $res[$i][$j][$n]['index'] = $n;
                $res[$i][$j][$n]['rating'] = $acc[$n];
            }
        }
    // Add general ratings
    for ($i = 0; $i < 2; $i++) {
        $lines = $values['counts'][$i];
        for ($n = 0; $n < $lines; $n++) {
            $res[$i][0][$n]['index'] = $n;
            $res[$i][0][$n]['rating'] = $res[$i][1][$n]['rating'] + $res[$i][2][$n]['rating'];
        }
    }
    // Sort
    for ($i = 0; $i < count($res); $i++)
        for ($j = 0; $j < count($res[$i]); $j++) {
            $lines = count($res[$i][$j]);
            for ($n1 = 0; $n1 < $lines; $n1++) {
                $ind = $n1;
                for ($n2 = $n1 + 1; $n2 < $lines; $n2++)
                    if ($res[$i][$j][$ind]['rating'] < $res[$i][$j][$n2]['rating'])
                        $ind = $n2;
                if ($ind != $n1) {
                    $tmp = $res[$i][$j][$ind]['rating'];
                    $res[$i][$j][$ind]['rating'] = $res[$i][$j][$n1]['rating'];
                    $res[$i][$j][$n1]['rating'] = $tmp;
                    $tmp = $res[$i][$j][$ind]['index'];
                    $res[$i][$j][$ind]['index'] = $res[$i][$j][$n1]['index'];
                    $res[$i][$j][$n1]['index'] = $tmp;
                }
            }
        }

    return $res;
}

function loadFactors($type) {
    if (!is_numeric($type) || !($type >= 0 && $type < 4))
        return array();
    $res = array();
    $conn = connectDB();
    $result = myQuery($conn, "select caption from factors where type=?;", array($type));
    if ($result) {
        while ($row = mysql_fetch_assoc($result)) {
            $res[count($res)] = $row['caption'];
        }
    }
    closeDB($conn);
    return $res;
}

?>
